package com.px.common.util;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class FastUtil {
    public static String randomAlphanumeric(int length) {
        return new Random()
                .ints(48, 123)
                .filter(i -> i < 58 || (i > 64 && i < 91) || i > 96)
                .mapToObj(i -> (char) i)
                .limit(length)
                .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
                .toString();
    }

    public static String randomNumeric(int length) {
        return new Random()
                .ints(48, 58)
                .mapToObj(i -> (char) i)
                .limit(length)
                .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
                .toString();
    }

    /*
    * 红包拆分(算法)
    * */
    public static List<String> randomRp(BigDecimal money, Integer totalCount) {
        if (totalCount < 2)
            return new ArrayList<String>() {{
                add(String.format("%.2f", money));
            }};

        int intMoney = (int) (money.doubleValue() * 10);
        List<Integer> rangeNum = IntStream.range(0, intMoney).boxed().collect(Collectors.toList());
        List<Integer> res = new ArrayList<>();
        IntStream.range(0, totalCount - 1).sequential().forEach(r -> new Random()
                .ints(0, rangeNum.size() - 1)
                .limit(1)
                .forEach(i -> res.add(rangeNum.remove(i))));
        Collections.sort(res);
        List<Integer> subRes = new ArrayList<>();
        final Integer[] cur = {-1};
        res.stream().sequential().forEach(v -> {
            subRes.add(v - cur[0]);
            cur[0] = v;
        });
        subRes.add(intMoney - 1 - res.get(res.size() - 1));
        return subRes.stream().parallel().map(v -> String.format("%.2f", v / 10.)).collect(Collectors.toList());
    }

    public static List<String> randomRpB(BigDecimal money, Integer amount) {
        if (amount < 2)
            return Collections.unmodifiableList(Arrays.asList(String.format("%.2f", money)));
        int intMoney = (int) (money.doubleValue() * 10);
        List<Integer> rangeNum = new ArrayList<>();
        IntStream.range(0, intMoney).forEach(rangeNum::add);
        List<Integer> res = new ArrayList<>();
        IntStream.range(0, amount - 1).forEach(r -> new Random()
                .ints(0, rangeNum.size() - 1)
                .limit(1)
                .forEach(i -> res.add(rangeNum.remove(i))));
        Collections.sort(res);

        AtomicInteger cur = new AtomicInteger(-1);
        List<Integer> subRes = res.stream().sequential().map(v -> {
            int diff = v - cur.get();
            cur.set(v);
            return diff;
        }).skip(0).mapToInt(v -> v).collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

//        subRes.add(intMoney - subRes.stream().mapToInt(Integer::intValue).sum());
        subRes.add(intMoney - 1 - res.get(res.size() - 1));
        return subRes.stream().map(v -> String.format("%.2f", v / 10.)).collect(Collectors.toList());
    }

    private static final String[] IP_HEADER_CANDIDATES = {
            "X-Forwarded-For",
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "HTTP_VIA",
            "REMOTE_ADDR"};

    public static String getClientIP(HttpServletRequest httpServletRequest) {
        for (String header : IP_HEADER_CANDIDATES) {
            String ipList = httpServletRequest.getHeader(header);
            if (ipList != null && ipList.length() != 0 && !"unknown".equalsIgnoreCase(ipList)) {
                return ipList.split(",")[0];
            }
        }
        return httpServletRequest.getRemoteAddr();
    }
}
